#include "config.h"
#include <cjson/cJSON.h> //cjson
#include <stdio.h>
#include <stdlib.h> //malloc
#include <string.h> //strdup

//读取配置文件中的内容
//参数：配置文件路径
//返回值：配置文件内容
char *read_file(char *path)
{
    long size = 0;
    char *buf = NULL;
    //打开文件
    FILE *fp = fopen(path, "r");
    if (fp == NULL)
    {
        //打印错误信息
        perror("Open file error");
        return NULL;
    }

    //打开成功
    //获取文件大小
    //将文件流指针移动到文件末尾，获取文件末尾的偏移
    //参数1：文件流指针
    //参数2：偏移长度
    //参数3：偏移的起始位置(头部，当前，尾部)
    fseek(fp, 0, SEEK_END);
    //获取当前文件流指针的位置
    size = ftell(fp);
    //分配内存（堆）
    buf = malloc(size + sizeof(""));
    if (buf == NULL)
    {
        perror("Memory allocation error");
        fclose(fp);
        return NULL;
    }
    //将文件流指针复位回到文件头
    fseek(fp, 0, SEEK_SET);
    //将文件的内容读取到内存中
    //参数1：保存文件内容的内存地址
    //参数2：一次读取大小
    //参数3：读取次数
    //参数4：文件流指针
    //返回值：读取次数（注意不是字节数）
    if (fread(buf, 1, size, fp) != size)
    {
        perror("read file error");
        fclose(fp);
        free(buf);
        return NULL;
    }

    buf[size] = 0;

    //关闭文件
    fclose(fp);

    return buf;
}

//解析配置文件内容
//参数1：配置文件内容（JSON字符串）
//参数2：配置参数结构体指针
//返回值：0 - 成功，1 - 失败
int parse_config(char *json, struct config *cfg)
{
    int retval = 0;
    cJSON *obj = cJSON_Parse(json);
    if (!obj)
    {
        //解析配置文件出错
        const char *error = cJSON_GetErrorPtr();
        if (error)
        {
            printf("Parse error: %s\n", error);
        }
        return 1;
    }
    cJSON *server_url = cJSON_GetObjectItem(obj, "server_url");
    cJSON *client_id = cJSON_GetObjectItem(obj, "client_id");
    cJSON *topic_sub = cJSON_GetObjectItem(obj, "topic_sub");
    cJSON *topic_pub = cJSON_GetObjectItem(obj, "topic_pub");
    cJSON *api_key = cJSON_GetObjectItem(obj, "api_key");
    cJSON *secret_key = cJSON_GetObjectItem(obj, "secret_key");
    //检查配置文件中是否包含所有参数
    if (!server_url || !client_id || !topic_sub || !topic_pub || !api_key || !secret_key)
    {
        printf("too few parameters");
        retval = 1;
    }

    // cJSON_Delete之后字符串不存在，需要复制一次
    cfg->server_url = strdup(server_url->valuestring);
    cfg->client_id = strdup(client_id->valuestring);
    cfg->topic_sub = strdup(topic_sub->valuestring);
    cfg->topic_pub = strdup(topic_pub->valuestring);
    cfg->api_key = strdup(api_key->valuestring);
    cfg->secret_key = strdup(secret_key->valuestring);

    cJSON_Delete(obj);
    return retval;
}

//读取配置文件并解析
//参数1：配置文件路径
//参数2：配置参数结构体
//返回值：0 - 成功，1 - 失败
int parse_file(char *path, struct config *cfg)
{
    char *content = read_file(path);
    if (!content)
    {
        return 1;
    }

    if (parse_config(content, cfg))
    {
        free(content);
        return 1;
    }
    free(content);
    return 0;
}
